package org.session.util;

import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * A descriptor for querying system properties.
 */
public final class SystemDescriptor {

    public static String getPropertyByName(final String propertyName) {
        String propertyValue = null;

        if (Property.getAllPropertyNames().contains(propertyName)) {
            propertyValue = System.getProperty(propertyName);
        } else {
            throw new IllegalArgumentException("Property=" + propertyName
                    + " is not a supported system property.");
        }

        return propertyValue;
    }

    public static Map<String, String> getAllSystemProperties() {
        String propertyName = null;
        Map<String, String> propertyMap = new HashMap<String, String>();
        for (Property property : Property.getAllProperties()) {
            propertyName = property.getPropertyName();
            propertyMap.put(propertyName, getPropertyByName(propertyName));
        }

        return Collections.unmodifiableMap(propertyMap);
    }

    /**
     * An enumeration of supported system properties for querying.
     */
    public enum Property {
        JAVA_CLASS_VERSION("java.class.version"), JAVA_VERSION("java.version"), JAVA_HOME(
                "java.home"), JVM_VERSION("java.vm.version"), JAVA_CLASSPATH(
                "java.class.path"), JAVA_LIBPATH("java.library.path"), OS_NAME(
                "os.name"), OS_ARCH("os.arch"), OS_VERSION("os.version"), FILE_SEPARATOR(
                "file.separator"), PATH_SEPARATOR("path.separator"), LINE_SEPARATOR(
                "line.separator");

        private final String propertyName;

        private Property(final String propertyName) {
            this.propertyName = propertyName;
        }

        // Bean methods
        public String getPropertyName() {
            return propertyName;
        }

        public static Set<Property> getAllProperties() {
            return Collections.unmodifiableSet(EnumSet.of(JAVA_CLASS_VERSION,
                    JAVA_VERSION, JAVA_HOME, JVM_VERSION, JAVA_CLASSPATH,
                    JAVA_LIBPATH, OS_NAME, OS_ARCH, OS_VERSION, FILE_SEPARATOR,
                    PATH_SEPARATOR, LINE_SEPARATOR));
        }

        public static Set<String> getAllPropertyNames() {
            Set<String> propertySet = new HashSet<String>();
            propertySet.add(JAVA_CLASS_VERSION.getPropertyName());
            propertySet.add(JAVA_VERSION.getPropertyName());
            propertySet.add(JAVA_HOME.getPropertyName());
            propertySet.add(JVM_VERSION.getPropertyName());
            propertySet.add(JAVA_CLASSPATH.getPropertyName());
            propertySet.add(JAVA_LIBPATH.getPropertyName());
            propertySet.add(OS_NAME.getPropertyName());
            propertySet.add(OS_ARCH.getPropertyName());
            propertySet.add(OS_VERSION.getPropertyName());
            propertySet.add(FILE_SEPARATOR.getPropertyName());
            propertySet.add(PATH_SEPARATOR.getPropertyName());
            propertySet.add(LINE_SEPARATOR.getPropertyName());

            return Collections.unmodifiableSet(propertySet);
        }

        @Override
        public String toString() {
            return "[Property name=" + propertyName + "]";
        }
    }

    /*
     * Prevent instance escape at all costs.
     */
    private SystemDescriptor() {
    }

}
